package okdeeplink;

import android.app.PendingIntent;
import android.util.Log;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Consumer;
import io.reactivex.observers.DisposableObserver;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.AsyncSubject;
import io.reactivex.subjects.BehaviorSubject;


/**
 * Created by zhangqijun on 2017/5/5.
 */

public class RealCallChain implements Interceptor.Call {


    private final List<Interceptor> interceptors;
    private int index;
    private Request request;

    public final BehaviorSubject<Interceptor> interceptorSubject = BehaviorSubject.create();

    public final AsyncSubject<Request> requestSubject = AsyncSubject.create();

    private int timeout = 0;

    public RealCallChain(List<Interceptor> interceptors, int index, Request request) {
        this.interceptors = interceptors;
        this.index = index;
        this.request = request;
    }

    public RealCallChain setTimeout(int timeout) {
        this.timeout = timeout;
        return this;
    }

    public void call() {

        Observable.just(1)
                .observeOn(Schedulers.io())
                .subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(@NonNull Integer integer) {
                        try{
                            proceed();
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                });


        Observable<Interceptor> observable = interceptorSubject;
        if (timeout > 0) {
            observable = interceptorSubject.timeout(timeout, TimeUnit.SECONDS);
        }
        observable.subscribe(new DisposableObserver<Interceptor>() {
            @Override
            public void onNext(@NonNull Interceptor interceptor) {
            }

            @Override
            public void onError(@NonNull Throwable e) {
                requestSubject.onError(new TimeoutException());
            }

            @Override
            public void onComplete() {
            }
        });
    }


    @Override
    public Request getRequest() {
        return request;
    }


    @Override
    public void proceed(Request request) {
        this.request = request;
        proceed();
    }

    public Observable<Request> getRequestObservable() {
        return requestSubject
                //.cache()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    public void realCall() {
        requestSubject.onNext(request);
        requestSubject.onComplete();
    }

    @Override
    public void proceed() {

        if (index >= interceptors.size()) {
            realCall();
            return;
        }
        final Interceptor interceptor = interceptors.get(index);
        Observable
                .just(1)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(@NonNull Integer integer) throws Exception {
                        interceptor.intercept(RealCallChain.this);
                    }
                });

        interceptorSubject.onNext(interceptor);
        index = index + 1;
    }

    @Override
    public void cancel() {
        requestSubject.onComplete();
         //requestSubject.onError(new PendingIntent.CanceledException());
    }
}
